<script setup>
import { onMounted } from 'vue'
import {
  Viewer,
  createWorldTerrain,
  ArcGisMapServerImageryProvider,
  Cartesian3,
  Math,
  Cesium3DTileset,
  IonResource,
  Cesium3DTileStyle,
  HorizontalOrigin,
  VerticalOrigin,
  HeightReference,
  Color,
  Cartographic,
  Cartesian4,
  PostProcessStage,
  Matrix4,
  Quaternion,
  Matrix3,
  WebMapTileServiceImageryProvider
} from 'cesium'
// import { useStore } from '@/stores/counter'

// const store = useStore()
let lastStageArr = []
// 圆扩散
function showCircleScan(viewer,r,color,d) {
  var cartographicCenter = new Cartographic(
    Math.toRadians(117.79086),
    Math.toRadians(30.095),
    32,
  )
  // var scanColor = new Color(0.0, 1.0, 0.0, 1)
  let lastStage = addCircleScanPostStage(
    viewer,
    cartographicCenter,
    r,
    color,
    d,
  )
  lastStageArr.push(lastStage);
}

// showRadarScan() // 雷达扫描
// function showRadarScan() {
//   var cartographicCenter = new Cartographic(
//     Math.toRadians(117.270739),
//     Math.toRadians(31.84309),
//     32,
//   )
//   var scanColor = new Color(1.0, 0.0, 0.0, 1)

//   lastStage = addRadarScanPostStage(
//     viewer,
//     cartographicCenter,
//     1000,
//     scanColor,
//     3000,
//   )
// }

// 清除
// 

/*
          添加扩散效果扫描线
          viewer
          cartographicCenter 扫描中心
          radius  半径 米
          scanColor 扫描颜色
          duration 持续时间 毫秒
        */
function addCircleScanPostStage(
  viewer,
  cartographicCenter,
  maxRadius,
  scanColor,
  duration,
) {
  var _Cartesian3Center = Cartographic.toCartesian(cartographicCenter)
  var _Cartesian4Center = new Cartesian4(
    _Cartesian3Center.x,
    _Cartesian3Center.y,
    _Cartesian3Center.z,
    1,
  )

  var _CartograhpicCenter1 = new Cartographic(
    cartographicCenter.longitude,
    cartographicCenter.latitude,
    cartographicCenter.height + 500,
  )
  var _Cartesian3Center1 = Cartographic.toCartesian(_CartograhpicCenter1)
  var _Cartesian4Center1 = new Cartesian4(
    _Cartesian3Center1.x,
    _Cartesian3Center1.y,
    _Cartesian3Center1.z,
    1,
  )

  var _time = new Date().getTime()

  var _scratchCartesian4Center = new Cartesian4()
  var _scratchCartesian4Center1 = new Cartesian4()
  var _scratchCartesian3Normal = new Cartesian3()

  var ScanPostStage = new PostProcessStage({
    fragmentShader: getScanSegmentShader(),
    uniforms: {
      u_scanCenterEC: function () {
        var temp = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center,
          _scratchCartesian4Center,
        )
        return temp
      },
      u_scanPlaneNormalEC: function () {
        var temp = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center,
          _scratchCartesian4Center,
        )
        var temp1 = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center1,
          _scratchCartesian4Center1,
        )

        _scratchCartesian3Normal.x = temp1.x - temp.x
        _scratchCartesian3Normal.y = temp1.y - temp.y
        _scratchCartesian3Normal.z = temp1.z - temp.z

        Cartesian3.normalize(
          _scratchCartesian3Normal,
          _scratchCartesian3Normal,
        )

        return _scratchCartesian3Normal
      },
      u_radius: function () {
        return (
          (maxRadius * ((new Date().getTime() - _time) % duration)) / duration
        )
      },
      u_scanColor: scanColor,
    },
  })

  viewer.scene.postProcessStages.add(ScanPostStage)
  return ScanPostStage
}
//扩散效果Shader
function getScanSegmentShader() {
  var scanSegmentShader =
    '\n\
                    uniform sampler2D colorTexture;\n\
                    uniform sampler2D depthTexture;\n\
                    varying vec2 v_textureCoordinates;\n\
                    uniform vec4 u_scanCenterEC;\n\
                    uniform vec3 u_scanPlaneNormalEC;\n\
                    uniform float u_radius;\n\
                    uniform vec4 u_scanColor;\n\
                    \n\
                    vec4 toEye(in vec2 uv,in float depth)\n\
                    {\n\
                                vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\n\
                                vec4 posIncamera = czm_inverseProjection * vec4(xy,depth,1.0);\n\
                                posIncamera = posIncamera/posIncamera.w;\n\
                                return posIncamera;\n\
                    }\n\
                    \n\
                    vec3 pointProjectOnPlane(in vec3 planeNormal,in vec3 planeOrigin,in vec3 point)\n\
                    {\n\
                                vec3 v01 = point - planeOrigin;\n\
                                float d = dot(planeNormal,v01);\n\
                                return (point-planeNormal * d);\n\
                    }\n\
                    float getDepth(in vec4 depth)\n\
                    {\n\
                                float z_window = czm_unpackDepth(depth);\n\
                                z_window = czm_reverseLogDepth(z_window);\n\
                                float n_range = czm_depthRange.near;\n\
                                float f_range = czm_depthRange.far;\n\
                                return (2.0 * z_window - n_range - f_range)/(f_range-n_range);\n\
                    } \n\
                    void main()\n\
                    {\n\
                                gl_FragColor = texture2D(colorTexture,v_textureCoordinates);\n\
                                float depth = getDepth(texture2D(depthTexture,v_textureCoordinates));\n\
                                vec4 viewPos = toEye(v_textureCoordinates,depth);\n\
                                vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz,u_scanCenterEC.xyz,viewPos.xyz);\n\
                                float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);\n\
                                if(dis<u_radius)\n\
                                {\n\
                                    float f = 1.0-abs(u_radius - dis )/ u_radius;\n\
                                    f = pow(f,4.0);\n\
                                    gl_FragColor = mix(gl_FragColor,u_scanColor,f);\n\
                                }\n\
                    } \n\ '
  return scanSegmentShader
}

/*
          添加雷达扫描线
          viewer
          cartographicCenter 扫描中心
          radius  半径 米
          scanColor 扫描颜色
          duration 持续时间 毫秒
        */
function addRadarScanPostStage(
  viewer,
  cartographicCenter,
  radius,
  scanColor,
  duration,
) {
  var _Cartesian3Center = Cartographic.toCartesian(cartographicCenter)
  var _Cartesian4Center = new Cartesian4(
    _Cartesian3Center.x,
    _Cartesian3Center.y,
    _Cartesian3Center.z,
    1,
  )

  var _CartographicCenter1 = new Cartographic(
    cartographicCenter.longitude,
    cartographicCenter.latitude,
    cartographicCenter.height + 500,
  )
  var _Cartesian3Center1 = Cartographic.toCartesian(_CartographicCenter1)
  var _Cartesian4Center1 = new Cartesian4(
    _Cartesian3Center1.x,
    _Cartesian3Center1.y,
    _Cartesian3Center1.z,
    1,
  )

  var _CartographicCenter2 = new Cartographic(
    cartographicCenter.longitude + Math.toRadians(0.001),
    cartographicCenter.latitude,
    cartographicCenter.height,
  )
  var _Cartesian3Center2 = Cartographic.toCartesian(_CartographicCenter2)
  var _Cartesian4Center2 = new Cartesian4(
    _Cartesian3Center2.x,
    _Cartesian3Center2.y,
    _Cartesian3Center2.z,
    1,
  )
  var _RotateQ = new Quaternion()
  var _RotateM = new Matrix3()

  var _time = new Date().getTime()

  var _scratchCartesian4Center = new Cartesian4()
  var _scratchCartesian4Center1 = new Cartesian4()
  var _scratchCartesian4Center2 = new Cartesian4()
  var _scratchCartesian3Normal = new Cartesian3()
  var _scratchCartesian3Normal1 = new Cartesian3()

  var ScanPostStage = new PostProcessStage({
    fragmentShader: getRadarScanShader(),
    uniforms: {
      u_scanCenterEC: function () {
        return Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center,
          _scratchCartesian4Center,
        )
      },
      u_scanPlaneNormalEC: function () {
        var temp = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center,
          _scratchCartesian4Center,
        )
        var temp1 = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center1,
          _scratchCartesian4Center1,
        )
        _scratchCartesian3Normal.x = temp1.x - temp.x
        _scratchCartesian3Normal.y = temp1.y - temp.y
        _scratchCartesian3Normal.z = temp1.z - temp.z

        Cartesian3.normalize(
          _scratchCartesian3Normal,
          _scratchCartesian3Normal,
        )
        return _scratchCartesian3Normal
      },
      u_radius: radius,
      u_scanLineNormalEC: function () {
        var temp = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center,
          _scratchCartesian4Center,
        )
        var temp1 = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center1,
          _scratchCartesian4Center1,
        )
        var temp2 = Matrix4.multiplyByVector(
          viewer.camera._viewMatrix,
          _Cartesian4Center2,
          _scratchCartesian4Center2,
        )

        _scratchCartesian3Normal.x = temp1.x - temp.x
        _scratchCartesian3Normal.y = temp1.y - temp.y
        _scratchCartesian3Normal.z = temp1.z - temp.z

        Cartesian3.normalize(
          _scratchCartesian3Normal,
          _scratchCartesian3Normal,
        )

        _scratchCartesian3Normal1.x = temp2.x - temp.x
        _scratchCartesian3Normal1.y = temp2.y - temp.y
        _scratchCartesian3Normal1.z = temp2.z - temp.z

        var tempTime = ((new Date().getTime() - _time) % duration) / duration
        Quaternion.fromAxisAngle(
          _scratchCartesian3Normal,
          tempTime * Math.PI * 2,
          _RotateQ,
        )
        Matrix3.fromQuaternion(_RotateQ, _RotateM)
        Matrix3.multiplyByVector(
          _RotateM,
          _scratchCartesian3Normal1,
          _scratchCartesian3Normal1,
        )
        Cartesian3.normalize(
          _scratchCartesian3Normal1,
          _scratchCartesian3Normal1,
        )
        return _scratchCartesian3Normal1
      },
      u_scanColor: scanColor,
    },
  })
  viewer.scene.postProcessStages.add(ScanPostStage)

  return ScanPostStage
}

//雷达扫描线效果Shader
function getRadarScanShader() {
  var scanSegmentShader =
    'uniform sampler2D colorTexture;\n' +
    'uniform sampler2D depthTexture;\n' +
    'varying vec2 v_textureCoordinates;\n' +
    'uniform vec4 u_scanCenterEC;\n' +
    'uniform vec3 u_scanPlaneNormalEC;\n' +
    'uniform vec3 u_scanLineNormalEC;\n' +
    'uniform float u_radius;\n' +
    'uniform vec4 u_scanColor;\n' +
    'vec4 toEye(in vec2 uv, in float depth)\n' +
    ' {\n' +
    ' vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\n' +
    ' vec4 posInCamera =czm_inverseProjection * vec4(xy, depth, 1.0);\n' +
    ' posInCamera =posInCamera / posInCamera.w;\n' +
    ' return posInCamera;\n' +
    ' }\n' +
    'bool isPointOnLineRight(in vec3 ptOnLine, in vec3 lineNormal, in vec3 testPt)\n' +
    '{\n' +
    'vec3 v01 = testPt - ptOnLine;\n' +
    'normalize(v01);\n' +
    'vec3 temp = cross(v01, lineNormal);\n' +
    'float d = dot(temp, u_scanPlaneNormalEC);\n' +
    'return d > 0.5;\n' +
    '}\n' +
    'vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point)\n' +
    '{\n' +
    'vec3 v01 = point -planeOrigin;\n' +
    'float d = dot(planeNormal, v01) ;\n' +
    'return (point - planeNormal * d);\n' +
    '}\n' +
    'float distancePointToLine(in vec3 ptOnLine, in vec3 lineNormal, in vec3 testPt)\n' +
    '{\n' +
    'vec3 tempPt = pointProjectOnPlane(lineNormal, ptOnLine, testPt);\n' +
    'return length(tempPt - ptOnLine);\n' +
    '}\n' +
    'float getDepth(in vec4 depth)\n' +
    '{\n' +
    'float z_window = czm_unpackDepth(depth);\n' +
    'z_window = czm_reverseLogDepth(z_window);\n' +
    'float n_range = czm_depthRange.near;\n' +
    'float f_range = czm_depthRange.far;\n' +
    'return (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n' +
    '}\n' +
    'void main()\n' +
    '{\n' +
    'gl_FragColor = texture2D(colorTexture, v_textureCoordinates);\n' +
    'float depth = getDepth( texture2D(depthTexture, v_textureCoordinates));\n' +
    'vec4 viewPos = toEye(v_textureCoordinates, depth);\n' +
    'vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);\n' +
    'float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);\n' +
    'float twou_radius = u_radius * 2.0;\n' +
    'if(dis < u_radius)\n' +
    '{\n' +
    'float f0 = 1.0 -abs(u_radius - dis) / u_radius;\n' +
    'f0 = pow(f0, 64.0);\n' +
    'vec3 lineEndPt = vec3(u_scanCenterEC.xyz) + u_scanLineNormalEC * u_radius;\n' +
    'float f = 0.0;\n' +
    'if(isPointOnLineRight(u_scanCenterEC.xyz, u_scanLineNormalEC.xyz, prjOnPlane.xyz))\n' +
    '{\n' +
    'float dis1= length(prjOnPlane.xyz - lineEndPt);\n' +
    'f = abs(twou_radius -dis1) / twou_radius;\n' +
    'f = pow(f, 3.0);\n' +
    '}\n' +
    'gl_FragColor = mix(gl_FragColor, u_scanColor, f + f0);\n' +
    '}\n' +
    '}\n'
  return scanSegmentShader
}

onMounted(() => {
  const custom = new WebMapTileServiceImageryProvider({
    url:
      'http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=ee361157630a45dcd55bf5d1a4a3d789',
     layer: "tonglingjkqmap",
                style: "default",
                format: "image/png",
                 maximumLevel: 12,
                tileMatrixSetID:"GoogleMapsCompatible"
  })
  const viewer = new Viewer('cesiumContainer', {
    //不创建小部件
    baseLayerPicker: false,
    //设置图像提供的程序
    imageryProvider: custom,
    //
    terrainProvider: createWorldTerrain({
      requestWaterMask: true,
      requestVertexNormals: true,
    }),
  })

  viewer.scene.globe.depthTestAgainstTerrain = true //开启深度检测
  viewer.cesiumWidget.creditContainer.style.display = 'none' //去cesium logo水印 或 css

  var entity = viewer.entities.add({
    name: '点',
    position: Cartesian3.fromDegrees(117.790861, 30.975, 43.48),
    billboard: {
      image: './marker/acting.png',
      scale: 1,
      horizontalOrigin: HorizontalOrigin.CENTER,
      verticalOrigin: VerticalOrigin.BOTTOM,
      heightReference: HeightReference.CLAMP_TO_GROUND,
    },
  })
  viewer.flyTo(entity)
  let color1 = new Color(1.0,0.0,0.0,1)
  let color2 = new Color(1.0,1.0,0.0,1)
  let color3 = new Color(0.0,1.0,0.0,1)
  showCircleScan(viewer,1000,color3,3000) 
  showCircleScan(viewer,500,color2,3000) 
  showCircleScan(viewer,250,color1,3000) 
  // viewer.camera.setView({
  //   destination: Cartesian3.fromDegrees(117.79086112976076, 30.975, 2000),
  //   orientation: {
  //     heading: Math.toRadians(175.0),
  //     pitch: Math.toRadians(-35.0),
  //   },
  // })

  // viewer.camera.setView({
  //   destination: new Cartesian3(1332761, -4662399, 4137888),
  //   orientation: {
  //     heading: 0.66,
  //     pitch: -0.6,
  //   },
  // })

  // var city = viewer.scene.primitives.add(
  //   new Cesium3DTileset({ url: IonResource.fromAssetId(3839) }),
  // )
  // //设置3D样式
  // const heightStyle = new Cesium3DTileStyle({
  //   color: {
  //     conditions: [
  //       ['${height} >= 300', 'rgba(45,0,75,0.5)'],
  //       ['${height} >= 200', 'rgba(102,71,151,0.5)'],
  //       ['${height} >= 100', 'rgba(179,56,25,0.5)'],
  //       ['${height} >= 50', 'rgba(33,176,75,0.5)'],
  //       ['${height} >= 25', 'rgba(135,230,275,0.5)'],
  //       ['${height} >= 10', 'rgba(151,10,175,0.5)'],
  //       ['${height} >= 5', 'rgba(300,106,125,0.5)'],
  //       ['true', 'rgba(127,59,8,1)'],
  //     ],
  //   },
  // })
  // city.style = heightStyle
})
</script>

<template>
  <div id="app">
    <div id="cesiumContainer"></div>
  </div>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
html,
body,
#cesiumContainer {
  width: 100%;
  height: 100%;
}
</style>
